import  File from './File.js'
import  Block from './Block.js'
import Square from "./Square.js";
import  Row from './Row.js'

export default class Pack {

    /**
     * 第一个块是用来装载基本信息，
     * 比如，这个模块叫什么，
     * 目录起始块到结束块，（通常目录丢到最后）
     */
    constructor(){
        let buff=new Uint8Array(1250)
        this.list=[ buff];
        this.length=1;
        this.paths=new File();
        this.index=1;
        this.headRow=new Row();
        this.files={};
    }

    /**
     *  加载 数据
     * @param data
     */
    loadData(data){
        let _this=this;
        let length=0;
        this.files={};
        let buff= new Uint8Array(data);
        let listBlock= Block.buffToBlocks(buff);
        _this.list=listBlock;
        let headBlock   = _this.list[0];
          let head=new File();
          head.loadData(headBlock);
          head.findData(0,0,null,this.analysisHead.bind(this));
        this.analysisIndexes();   // 解析 索引
    }
    /**
     * 获取全部数据
     * @returns {uint8array[]|*[]}
     */
    outData(){
        let _this=this;
        let suoyin=1

        let paths=this.paths;
        let newpath =new File();
        let buff=new Uint8Array(1250)
        let resList=[buff];
        /**
         * 查找临时文件里面有没有内容。
         * 如果有  从文件里面直接导出数据；
         * 如果 没有从list里面读取文件。
         */
        for(let i=0;i<paths.list.length;i++){
            let path=paths.list[i];
            let length=resList.length;
            if(_this.files[i]){
               let fileBuff=  _this.files[i].outData();
                let fileBlock= Block.buffToBlocks(fileBuff);
               resList.push(...fileBlock)
                path.list[0]=new Row(length, length+fileBlock.length,null,2)
                newpath.addData(0,null,null,path)

            }else {
                let row=path.list[0];
                let fileBlock= _this.list.slice(parseInt(row.find(1)),parseInt(row.find(2)))
                resList.push(...fileBlock);
                path.list[0]=new Row(length, length+fileBlock.length-1,null,2)
                newpath.addData(0,null,null,path)
            }
        }
        /**
         * 保存目录数据
         * 保存索引
         * 输出数据
         */

        let resListLength=resList.length;
        let pathsBuff=newpath.outData();
        let pathBlock=   Block.buffToBlocks(pathsBuff);
        resList.push(...pathBlock)
        let file =new File();
        let  squares=new Square();
        squares.addRow(new Row(suoyin, resListLength,(resListLength+pathBlock.length),suoyin))
        file.addData(null,null,null,squares);
        let block= Block.buffToBlocks(file.outData()) ;
        resList[0]=block[0];
         let resBuff=Block.blocksToBuff(resList)
        return resBuff;
    }
    /**
     * 解析索引
     * @returns {*|number|void}
     */
    analysisHead(FileId,BlockId,RowId,dataThis){
       this.headRow= dataThis.list[0]
    }
    /**
     * 解析目录
     * @returns {*|number|void}
     */
    analysisIndexes(){
        let path=   this.headRow;
        let pathBlock=this.list.slice(parseInt(path.find(2)),parseInt(path.find(3)));
        let file=new File();
        file.loadData(Block.blocksToBuff(pathBlock));
        this.paths= file;
    }
    /**
     *
     * @param FileId
     * @param SquareId
     * @param RowsId
     * @param data
     * @returns {number|*}
     */
    addData(fileId,squareId,rowsId,data){
        if(fileId!==null){
            if(!this.files[fileId]){
                let file= this.findFile(fileId);
               this.files[fileId]=file;

            }
            return  this.files[fileId].addData(fileId,squareId,rowsId,data)

        }else {
            let square =new Square();

            let length=this.list.length;
           let blocks=  Block.buffToBlocks(data.outData())
            let path=new Row(length, length+blocks.length,null,2)
            square.addData(null,null,null,path)
            let index= this.paths.addData(0,null,null,square)

            this.list.push(...blocks);
            return index;
        }

    }



    /**
     * 获取 文件
     * @param fileId
     */
    findFile(fileId){
        let row=  this.paths.list[fileId].list[0]
        let fileBlock= this.list.slice(parseInt(row.find(1)),parseInt(row.find(2)))

        let file =new File();
        file.loadData(Block.blocksToBuff(fileBlock))
        return file;
    }

    /**
     *
     * @param FileId
     * @param SquareId
     * @param RowId
     * @param id
     */
    findData(fileId,squareId,rowId,func) {
        let _this = this;
        if (fileId != null) {
            if (_this.files[fileId]) {
                return _this.files[fileId].findData(fileId, squareId, rowId, func)
            }
            let file = _this.findFile(fileId);
            _this.files[fileId] = file;
            return _this.files[fileId].findData(fileId, squareId, rowId, func)

        }
        return func(fileId, squareId, rowId, _this);
    }
}